package com.final_project.zombiemenace.model;

import com.final_project.zombiemenace.screens.GameScreenZombie;
import com.final_project.zombiemenace.util.ConstantsUtil;

public class Bullet {
	private static final int MIN_DISTANCE_TO_ZOMBIE = 18;
	private static final int BULLET_DAMAGE = 20;
	private float coordX;
	private float coordY;
	private float speedX;
	private float speedY;
	private boolean visible;
	private float angleRotation;

	/**
	 * Creating a new Bullet object by given start X and start Y coordinate, and
	 * angle for calculating the direction and speed
	 * 
	 * @param startX
	 *            - float value representing the x starting coordinate of the
	 *            bullet
	 * @param startY
	 *            - float value representing the y starting coordinate of the
	 *            bullet
	 * @param angle
	 *            float value representing the the angle of the bullet
	 */
	public Bullet(float startX, float startY, float angle) {
		coordX = startX;
		coordY = startY;
		setBulletSpeed();
		visible = true;
		angleRotation = (float) (angle * (180 / Math.PI));
	}

	/**
	 * Method that sets the speed of the bullet according to its angle of
	 * rotation. Rotation is in degrees and bullet orientation is defined by
	 * this angleRotation
	 */
	private void setBulletSpeed() {

		if (angleRotation >= -45f && angleRotation <= 45f) {
			speedX = 10;
			speedY = (float) (angleRotation / 4.5);
		} else if (angleRotation < -45f && angleRotation >= -135f) {
			speedY = -10;
			speedX = (float) ((angleRotation + 90) / 4.5);
		} else if (angleRotation < -135f || angleRotation > 135f) {
			speedX = -10;
			if (angleRotation > 135f) {
				speedY = (float) ((180 - angleRotation) / 4.5);
			} else {
				speedY = (float) -((180 + angleRotation) / 4.5);
			}
		} else if (angleRotation >= 45f && angleRotation <= 135f) {
			speedY = 10;
			speedX = (float) -((angleRotation - 90) / 4.5);
		}
	}

	/**
	 * Update bullet state and location on the screen
	 */
	public void update() {
		setBulletSpeed();
		move();
		if (isOutsideScreenBorders()) {
			this.visible = false;
		} else {
			checkCollision();
		}
	}

	/**
	 * Check if bullet has reached outside the screen
	 * 
	 * @return - true if the bullet is outside the screen, false if it's inside
	 */
	private boolean isOutsideScreenBorders() {
		return this.coordX + this.speedX + Assets.bullet.getWidth() > ConstantsUtil.MAX_SCREEN_WIDTH
				|| this.coordX + this.speedX + Assets.character.getWidth() / 2 < ConstantsUtil.MIN_SCREEN_WIDTH
				|| this.coordY + this.speedY + Assets.bullet.getHeight() > ConstantsUtil.MAX_SCREEN_HEIGHT
				|| this.coordY + this.speedY + Assets.character.getHeight() / 2 < ConstantsUtil.MIN_SCREEN_HEIGHT;
	}

	/**
	 * Changes the x and y coordinates of the bullet by adding bullet speed
	 */
	private void move() {
		coordX += speedX;
		coordY += speedY;
	}

	/**
	 * Check for collision between zombies and the currrent bullet if a
	 * collision has occured
	 */
	private void checkCollision() {
		for (Zombie zombie : GameScreenZombie.zombieHorde) {
			if (Circle.calculateDistanceBetweenPoints(this.coordX, this.coordY,
					zombie.getCenterX(), zombie.getCenterY()) <= MIN_DISTANCE_TO_ZOMBIE) {
				zombie.setHealth(zombie.getHealth() - BULLET_DAMAGE);
				this.visible = false;
				return;
			}
		}
	}

	/* Getters and setters */

	public float getCoordX() {
		return coordX;
	}

	public float getCoordY() {
		return coordY;
	}

	public float getSpeedX() {
		return speedX;
	}

	public float getSpeedY() {
		return speedY;
	}

	public boolean isVisible() {
		return visible;
	}

	public void setVisible(boolean visible) {
		this.visible = visible;
	}

	public float getAngleRotation() {
		return angleRotation;
	}

}
